package com.mini.grpc.spring.server;

import com.mini.grpc.server.Server;
import com.mini.grpc.server.ServerBuilder;
import com.mini.grpc.server.ServerInterceptor;
import com.mini.grpc.server.ServerInterceptors;
import com.mini.grpc.server.ServerServiceDefinition;
import com.mini.grpc.spring.autoconfigure.GrpcServerProperties;
import com.mini.grpc.spring.server.GrpcServiceRegistry.GrpcServiceInfo;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;

/**
 * gRPC服务器管理器
 * 负责启动、停止和管理gRPC服务器
 * 
 * @author Mini-gRPC
 */
@Component
public class GrpcServerManager implements InitializingBean, DisposableBean {
    
    private static final Logger logger = Logger.getLogger(GrpcServerManager.class.getName());
    
    @Autowired
    private GrpcServerProperties properties;
    
    @Autowired
    private GrpcServiceRegistry serviceRegistry;
    
    @Autowired
    private ApplicationContext applicationContext;
    
    private Server server;
    private volatile boolean started = false;
    
    @Override
    public void afterPropertiesSet() throws Exception {
        if (properties.isEnabled()) {
            startServer();
        }
    }
    
    @Override
    public void destroy() throws Exception {
        stopServer();
    }
    
    /**
     * 启动gRPC服务器
     */
    public synchronized void startServer() throws IOException {
        if (started) {
            logger.warning("gRPC server is already started");
            return;
        }
        
        logger.info("Starting gRPC server on port " + properties.getPort());
        
        ServerBuilder<?> serverBuilder = ServerBuilder.forPort(properties.getPort());
        
        // 配置服务器参数
        configureServer(serverBuilder);
        
        // 注册所有服务
        registerServices(serverBuilder);
        
        // 构建并启动服务器
        server = serverBuilder.build();
        server.start();
        started = true;
        
        logger.info("gRPC server started successfully on port " + server.getPort());
        
        // 添加关闭钩子
        Runtime.getRuntime().addShutdownHook(new Thread(() -> {
            logger.info("Shutting down gRPC server due to JVM shutdown");
            try {
                stopServer();
            } catch (Exception e) {
                logger.severe("Error during server shutdown: " + e.getMessage());
            }
        }));
    }
    
    /**
     * 停止gRPC服务器
     */
    public synchronized void stopServer() throws InterruptedException {
        if (!started || server == null) {
            return;
        }
        
        logger.info("Stopping gRPC server...");
        
        server.shutdown();
        
        // 等待服务器优雅关闭
        if (!server.awaitTermination(properties.getShutdownTimeoutSeconds(), TimeUnit.SECONDS)) {
            logger.warning("Server did not terminate gracefully, forcing shutdown");
            server.shutdownNow();
            
            // 再次等待强制关闭
            if (!server.awaitTermination(5, TimeUnit.SECONDS)) {
                logger.severe("Server did not terminate after forced shutdown");
            }
        }
        
        started = false;
        logger.info("gRPC server stopped");
    }
    
    /**
     * 配置服务器参数
     * 
     * @param serverBuilder 服务器构建器
     */
    private void configureServer(ServerBuilder<?> serverBuilder) {
        // 设置最大消息大小
        if (properties.getMaxInboundMessageSize() > 0) {
            serverBuilder.maxInboundMessageSize(properties.getMaxInboundMessageSize());
        }
        
        if (properties.getMaxInboundMetadataSize() > 0) {
            serverBuilder.maxInboundMetadataSize(properties.getMaxInboundMetadataSize());
        }
        
        // 设置握手超时
        if (properties.getHandshakeTimeoutMillis() > 0) {
            serverBuilder.handshakeTimeout(properties.getHandshakeTimeoutMillis(), TimeUnit.MILLISECONDS);
        }
        
        // 设置执行器
        if (properties.getExecutorThreads() > 0) {
            // 这里可以配置自定义执行器
            logger.info("Using " + properties.getExecutorThreads() + " executor threads");
        }
    }
    
    /**
     * 注册所有服务
     * 
     * @param serverBuilder 服务器构建器
     */
    private void registerServices(ServerBuilder<?> serverBuilder) {
        List<GrpcServiceInfo> services = serviceRegistry.getAllServices();
        
        if (services.isEmpty()) {
            logger.warning("No gRPC services found to register");
            return;
        }
        
        logger.info("Registering " + services.size() + " gRPC services");
        
        for (GrpcServiceInfo serviceInfo : services) {
            try {
                ServerServiceDefinition serviceDefinition = serviceInfo.getServiceDefinition();
                List<ServerInterceptor> interceptors = serviceInfo.getInterceptors();
                
                // 应用拦截器
                if (!interceptors.isEmpty()) {
                    serviceDefinition = ServerInterceptors.intercept(serviceDefinition, interceptors);
                    logger.info("Applied " + interceptors.size() + " interceptors to service " + 
                              serviceInfo.getServiceName());
                }
                
                serverBuilder.addService(serviceDefinition);
                logger.info("Registered service: " + serviceInfo.getServiceName());
                
            } catch (Exception e) {
                logger.severe("Failed to register service " + serviceInfo.getServiceName() + ": " + e.getMessage());
                throw new RuntimeException("Failed to register service " + serviceInfo.getServiceName(), e);
            }
        }
    }
    
    /**
     * 获取服务器实例
     * 
     * @return 服务器实例
     */
    public Server getServer() {
        return server;
    }
    
    /**
     * 检查服务器是否已启动
     * 
     * @return 是否已启动
     */
    public boolean isStarted() {
        return started && server != null && !server.isShutdown();
    }
    
    /**
     * 获取服务器端口
     * 
     * @return 端口号
     */
    public int getPort() {
        return server != null ? server.getPort() : -1;
    }
    
    /**
     * 获取注册的服务数量
     * 
     * @return 服务数量
     */
    public int getServiceCount() {
        return serviceRegistry.getServiceCount();
    }
    
    /**
     * 阻塞等待服务器终止
     */
    public void awaitTermination() throws InterruptedException {
        if (server != null) {
            server.awaitTermination();
        }
    }
} 